package cn.hcbycloud.common.jwt.service.encryptionkey;


import cn.hcbycloud.common.core.constant.CommonConstant;
import cn.hcbycloud.common.core.exception.CustomizeException;
import cn.hutool.core.collection.CollUtil;

import javax.annotation.PostConstruct;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Map;

/**
 * @author gaoh
 * @desc 向内存中存取RSA密钥对
 * *****该bean由于将密钥对的字符串存储在了内存中，因此仅仅适用于在单体项目场景下调用******
 * *****基于安全考虑，单体项目使用时，每次容器重启，密钥对字符串会重新刷新*************
 * @date 2022年01月12日 下午 4:44
 */
@SuppressWarnings("all")
public class RsaEncryptionKeyCacheService {

    public static Map<String, String> RsaKeyMap = CollUtil.newHashMap();
    /**
     * RSA密钥对生成工具
     */
    private RsaEncryptionKeyService rsaEncryptionKeyService;

    public RsaEncryptionKeyCacheService(RsaEncryptionKeyService rsaEncryptionKeyService) {
        this.rsaEncryptionKeyService = rsaEncryptionKeyService;
    }

    /**
     * 初始化时将密钥对存储在内存中
     */
    @PostConstruct
    public void init() {
        try {
            RsaKeyMap = rsaEncryptionKeyService.generateKey();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取公钥字符串
     *
     * @return
     */
    public static String getJwtPublicKeyStr() {
        return RsaKeyMap.get(CommonConstant.PUBLIC_KEY);
    }


    /**
     * 获取私钥字符串
     *
     * @return
     */
    public static String getJwtPrivateKeyStr() {
        return RsaKeyMap.get(CommonConstant.PRIVATE_KEY);
    }

    /**
     * 获取私钥对象
     * @return
     */
    public static PrivateKey getPrivateKey() {
        try {
            byte[] result = Base64.getDecoder().decode(getJwtPrivateKeyStr());
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(result);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(priPKCS8);
        } catch (Exception e) {
            throw new CustomizeException("无法获取私钥对象", e);
        }
    }
}